﻿
using System;
using System.Collections.Generic;
using System.Text;
using Tao.Lua;
using System.Diagnostics;
using System.IO;

namespace TaoGL_UserControl
{
    class FileMgr
    {
        class srTempo
        {
            public int StartEvent;
            public int Tempo;		//Bpm
        };

        class srRhythm
        {
            public int Section;	//第幾小節
            public int Beat;		//4分之幾拍
            public int Event;		//第幾Event改變資料
        };

        class srNote
        {
            public int Ads;		//取出子譜位置點 
            public int NoteTime;	//Note時間
            public int TypeMode;	//模式(0:單擊 1:長按)
            public  int LongEndTime; //長按結束時間(實際結束時間)
            public int DurationTime;	//音效長度時間
            public int Velocity;		//打擊速度(按下去的速度,代表音量的大小)
            public int Timbre;			//音階(記錄使用那一個樂器)
            public string SndName;		//音樂名稱
        };


        class srMbx
        {
            public List<srTempo> LstChangeTempo;
            public List<srRhythm> LstChangeRhythm;
            public List<srNote>[] LstNote;	//存放每一軌的資料(固定為30列)
            public string BgSndName;
            public int BgPlayTime;		//背景音播放啟始時間(如果為 -1 表示沒有Bg)
            public int EndTime;		//歌曲結束時間

            public srMbx()
            {
                LstChangeTempo = new List<srTempo>();
                LstChangeRhythm = new List<srRhythm>();
                LstNote = new List<srNote>[30];
                for (int i = 0; i < LstNote.Length; i++)
                    LstNote[i] = new List<srNote>();
            }
        };

        srMbx m_MbxInfo;
             

       
        //==============================================================================
        public FileMgr()
        {
            m_MbxInfo = new srMbx();

        }

        //==============================================================================      
        //使用Lua方式載作檔案
        public int LoadMbxFile(string filename)
        {
            IntPtr L = Lua.luaL_newstate();
            Lua.lua_status(L);
            L = Lua.lua_open();
            Lua.luaopen_base(L);
            Lua.luaL_openlibs(L);
            if (Lua.luaL_dofile(L, PathMgr.Script + "readmbx.lua") > 0)
            {
                Debug.WriteLine("readmbx Lua File Error");
                return -1;
            }
            //----------------------------------------------------------------------------	
            //傳入"檔名" 讓 Lua去讀取資料
            Lua.lua_getglobal(L, "ReadMbxFile");
            Lua.lua_pushstring(L, filename);
            Lua.lua_call(L, 1, 0);
            //----------------------------------------------------------------------------	
            m_MbxInfo.LstChangeTempo.Clear();
            m_MbxInfo.LstChangeRhythm.Clear();
            foreach (List<srNote> lp in m_MbxInfo.LstNote)
                lp.Clear();
            //----------------------------------------------------------------------------	
            //取得ChangeTempo
            {
                Lua.lua_getglobal(L, "GetTempoInfoSize");
                Lua.lua_call(L, 0, 1);
                int n = Lua.lua_tointeger(L, -1);
                Lua.lua_pop(L, 1);

                for (int i = 0; i < n; i++)
                {
                    int DataAdr = 3;
                    Lua.lua_getglobal(L, "GetTempoInfoData");
                    Lua.lua_pushinteger(L, i);
                    Lua.lua_call(L, 1, 5);
                    srTempo sr = new srTempo();
                    sr.StartEvent = Lua.lua_tointeger(L, DataAdr);
                    sr.Tempo = Lua.lua_tointeger(L, ++DataAdr);
                    Lua.lua_pop(L, 5);
                    m_MbxInfo.LstChangeTempo.Add(sr);
                }
            }
            //----------------------------------------------------------------------------
            //取得 ChangeRhythm
            {
                Lua.lua_getglobal(L, "GetRhythmInfoSize");
                Lua.lua_call(L, 0, 1);
                int n = Lua.lua_tointeger(L, -1);
                Lua.lua_pop(L, 1);

                for (int i = 0; i < n; i++)
                {
                    int DataAdr = 3;
                    Lua.lua_getglobal(L, "GetRhythmInfoData");
                    Lua.lua_pushinteger(L, i);
                    Lua.lua_call(L, 1, 5);
                    srRhythm sr = new srRhythm();
                    sr.Section = Lua.lua_tointeger(L, DataAdr);
                    sr.Event = Lua.lua_tointeger(L, ++DataAdr);
                    sr.Beat = Lua.lua_tointeger(L, ++DataAdr);
                    Lua.lua_pop(L, 5);
                    m_MbxInfo.LstChangeRhythm.Add(sr);
                }
            }
            //----------------------------------------------------------------------------
            //取得 子譜資料
            {
                //取得共有幾條Bar
                Lua.lua_getglobal(L, "GetBarInfoSize");
                Lua.lua_call(L, 0, 1);
                int n = Lua.lua_tointeger(L, -1);
                Lua.lua_pop(L, 1);

                for (int i = 0; i < n; i++)
                {
                    //先取是那一條資料
                    int DataAdr = 3;
                    Lua.lua_getglobal(L, "GetBarInfoNum");
                    Lua.lua_pushinteger(L, i);
                    Lua.lua_call(L, 1, 2);
                    int p = Lua.lua_tointeger(L, DataAdr);
                    int q = Lua.lua_tointeger(L, ++DataAdr);
                    Lua.lua_pop(L, 2);

                    for (int j = 0; j < q; j++)
                    {
                        //取得Note數量
                        int LuaAdr = 3;
                        Lua.lua_getglobal(L, "GetBarInfoData");
                        Lua.lua_pushinteger(L, i);
                        Lua.lua_pushinteger(L, j);
                        Lua.lua_call(L, 2, 15);

                        srNote sr = new srNote();
                        sr.Ads = Lua.lua_tointeger(L, LuaAdr);                //Ads;
                        sr.NoteTime = Lua.lua_tointeger(L, ++LuaAdr);		//NoteTime
                        sr.TypeMode = Lua.lua_tointeger(L, ++LuaAdr);		//TypeMode
                        ++LuaAdr;									    	//長按距離
                        sr.LongEndTime = Lua.lua_tointeger(L, ++LuaAdr);	//長按結束時間
                        ++LuaAdr;									    	//難度
                        sr.DurationTime = Lua.lua_tointeger(L, ++LuaAdr);	//音效長度
                        ++LuaAdr;									    	//音階
                        sr.Velocity = Lua.lua_tointeger(L, ++LuaAdr);		//擊鍵速度
                        ++LuaAdr;									    	//長度
                        sr.Timbre = Lua.lua_tointeger(L, ++LuaAdr);			//音階
                        sr.SndName = Lua.lua_tostring(L, ++LuaAdr);			//名稱
                        Lua.lua_pop(L, 15);
                    }
                }
            }
            //----------------------------------------------------------------------------
            //取得 Bg資料
            {
                Lua.lua_getglobal(L, "GetBgInfoData");
                Lua.lua_call(L, 0, 5);
                int LuaAdr = 3;
                m_MbxInfo.BgSndName = Lua.lua_tostring(L, LuaAdr);		//歌曲名
                ++LuaAdr;									    		//Ads
                m_MbxInfo.BgPlayTime = Lua.lua_tointeger(L, ++LuaAdr);	//播放啟始時間		
                ++LuaAdr;									    		//音量		
                Lua.lua_pop(L, 5);
            }
            //----------------------------------------------------------------------------	
            //取得 結束點
            {
                Lua.lua_getglobal(L, "GetEndInfoData");
                Lua.lua_call(L, 0, 5);
                int LuaAdr = 3;
                m_MbxInfo.EndTime = Lua.lua_tointeger(L, ++LuaAdr);		//結束時間	
                Lua.lua_pop(L, 5);
            }
            Lua.lua_close(L);
            return 0;

        }
        //==============================================================================      
        //使用直接讀檔案方式載入檔案
        public int ReadMbxFile(string filename)
        {

            m_MbxInfo.LstChangeTempo.Clear();
            m_MbxInfo.LstChangeRhythm.Clear();
            foreach (List<srNote> lp in m_MbxInfo.LstNote)
                lp.Clear();


            FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read);
            StreamReader sr = new StreamReader(fs);


            if (sr.ReadLine() == "GW_MBX_TEXT")
            {

                string strData = string.Empty;
                while ((strData = sr.ReadLine()) != null)
                {
                    string[] strtmp = strData.ToString().Split(',');
                    switch (strtmp[0])
                    {

                        case "MBG_INFO":
                            m_MbxInfo.BgSndName = strtmp[1];
                            m_MbxInfo.BgPlayTime = Convert.ToInt32(strtmp[3]);
                            break;
                        case "MED_INFO":
                            m_MbxInfo.EndTime = Convert.ToInt32(strtmp[2]);

                            break;
                        case "MCT_INFO":
                            {
                                int tponum = Convert.ToInt32(strtmp[1]);
                                for (int i = 0; i < tponum; i++)
                                {

                                    string[] strtpo = sr.ReadLine().ToString().Split(',');
                                    srTempo p = new srTempo();
                                    p.StartEvent = Convert.ToInt32(strtpo[0]);
                                    p.Tempo = Convert.ToInt32(strtpo[1]);
                                    m_MbxInfo.LstChangeTempo.Add(p);
                                }
                            }

                            break;

                        case "MCR_INFO":
                            {
                                int rtmnum = Convert.ToInt32(strtmp[1]);
                                for (int i = 0; i < rtmnum; i++)
                                {
                                    string[] strrtm = sr.ReadLine().ToString().Split(',');
                                    srRhythm p = new srRhythm();
                                    p.Section = Convert.ToInt32(strrtm[0]);
                                    p.Event = Convert.ToInt32(strrtm[1]);
                                    p.Beat = Convert.ToInt32(strrtm[2]);
                                    m_MbxInfo.LstChangeRhythm.Add(p);
                                }
                            }
                            break;

                        case "MBR_INFO":
                            {
                                int posads = Convert.ToInt32(strtmp[1]);    //取得那一排Key
                                int notenum = Convert.ToInt32(strtmp[2]);   //數量

                                for (int i = 0; i < notenum; i++)
                                {
                                    string[] strbar = sr.ReadLine().ToString().Split(',');
                                    srNote p = new srNote();
                                    p.Ads = Convert.ToInt32(strbar[0]);
                                    p.NoteTime = Convert.ToInt32(strbar[1]);
                                    p.TypeMode = Convert.ToInt32(strbar[2]);
                                    p.LongEndTime = Convert.ToInt32(strbar[4]);
                                    p.DurationTime = Convert.ToInt32(strbar[6]);
                                    p.Velocity = Convert.ToInt32(strbar[8]);
                                    p.Timbre = Convert.ToInt32(strbar[10]);
                                    p.SndName = strbar[11];
                                    m_MbxInfo.LstNote[posads].Add(p);
                                }
                            }
                            break;
                        case "END":
                            sr.Close();
                            fs.Close();
                            return 0;
                    }
                }
            }
            else
            {

            }
            sr.Close();
            fs.Close();
            return 0;

        }


    }
}
